package com.company;

import java.io.*;
import java.util.ArrayList;
import java.util.List;

import static com.company.CodeInputAndScan.getChar;
import static com.company.CodeInputAndScan.point;
import static com.company.Lex.isDigit;
import static com.company.Lex.isLetter;

public class Operator_precedenceParsing {
    static List<String> expressionTxt=new ArrayList<String>();
    static int k;//栈顶指针
    static int j;
    static char Q;
    static char N;
    static char ch;
    static int errortime;
    static String reduce;
    static String a;//分析栈中的字符串
    static String lineExpressionTxt;//待分析的表达式
    static char[] nonTerminator={'E','T','F'};//非终结符表
    static char[] terminator={'+','-','*','/','(',')','i','#'};//终结符表
    static String[] productionTable={"E+T","E-T","T","T*F","T/F","F","(E)","i","E+F","E-F","E/F","E*F","E+E","E+i","E-i","E/i","E*i"};//产生式表
    static int[][] linkTable={
            {1,1,0,0,0,1,0,1},
            {1,1,0,0,0,1,0,1},
            {1,1,1,1,0,1,0,1},
            {1,1,1,1,0,1,0,1},
            {0,0,0,0,0,2,0,-1},
            {1,1,1,1,-1,1,-1,1},
            {1,1,1,1,-1,1,-1,1},
            {0,0,0,0,0,-1,0,2}
    };//模拟算符优先关系表,1表示优于,0表示低于,-1表示错误,2表示等于,顺序为+,-,*,/,(,),i

    public static void main(String[] args) {
        Operator_precedenceParsing operator_precedenceParsing=new Operator_precedenceParsing();
        expressionTxt=operator_precedenceParsing.readExpression();
        int i=0;
        while(i<5){
            errortime=0;
            lineExpressionTxt=expressionTxt.get(i);
            i++;
            point=0;

            k=1;
            a="##";

            do {
                ch=getChar(lineExpressionTxt);
                if(ch==';'){
                    ch=getChar(lineExpressionTxt);
                }

                if(inTerminator(a.charAt(k))){//判断是否为终结符
                    j=k;
                }else j=k-1;

                while(valueOfLink(a.charAt(j),ch)==1){
                    do {
                        Q=a.charAt(j);
                        if(inTerminator(a.charAt(j-1))){
                            j=j-1;
                        }else j=j-2;

                    }while (valueOfLink(a.charAt(j),Q)!=0);

                     reduce="";
                     for(int s=j+1;s<=k;s++){//把a[j+1]...a[k]归约为某个终结符N;
                        reduce=reduce+a.charAt(s);
                     }
                     for(int t=j+1;t<=k;t++){
                         a=a.substring(0,a.length()-1);
                     }

                    if(reduce.length()==1&&(isLetter(reduce.charAt(0))||isDigit(reduce.charAt(0)))&&reduce.charAt(0)!='i'){
                        N='i';
                    }else if(reduce.charAt(0)=='i'){
                        N='F';
                    }else if(reduce.length()>1){
                        int proNum=lookupReduce(reduce);
                        if(proNum==0||proNum==1||proNum==2||proNum==7||proNum==8||proNum==9||
                                proNum==10||proNum==11||proNum==12||proNum==13||proNum==14||proNum==15||proNum==16){
                            N='E';
                        }else if(proNum==3||proNum==4||proNum==5){
                            N='T';
                        }else if(proNum==6){
                            N='F';
                        }else{ error();}
                    }


                     k=j+1;
                     //analysisStak.push(N);
                     a=a+N;
                }

                while(inNonTerminator(a.charAt(a.length()-1))||a.charAt(a.length()-1)=='i'){
                    int proNum2=lookupReduce(a.charAt(a.length()-1)+"");
                    if(proNum2==5){
                        N='T';
                        a=a.substring(0,a.length()-1);
                        a=a+N;
                    }else if(proNum2==2){
                        N='E';
                        a=a.substring(0,a.length()-1);
                        a=a+N;
                    }else if(proNum2==7){
                        N='F';
                        a=a.substring(0,a.length()-1);
                        a=a+N;
                    }
                    else{break;}
                }

                if(a.equals("##E")&&ch=='#')break;

                if(valueOfLink(a.charAt(j),ch)==0||valueOfLink(a.charAt(j),ch)==2||(isDigit(ch)&&(isDigit(a.charAt(j))))){
                    k=k+1;
                    a=a+ch;
                }else{ error();break;}


            }while (a!="##E"||ch!='#');

            if(errortime==0) System.out.println("正确");
            else System.out.println("错误");
        }

    }

    public List<String> readExpression(){
            List<String> expressionTxt=new ArrayList<String>();
            String lineTxt="";

            File file=new File("expression");
            String filePath=file.getAbsolutePath();

            try {
                BufferedReader buffReader = new BufferedReader(new InputStreamReader(new FileInputStream(new File(filePath)), "utf-8"));
                while ((lineTxt = buffReader.readLine()) != null) {
                    expressionTxt.add(lineTxt);
                }
            }catch (Exception e){
                System.err.println("read errors :" + e);
            }

            return expressionTxt;

    }


    public static boolean inTerminator(char ch){
        return ch==terminator[0]||ch==terminator[1] ||ch==terminator[2]||ch==terminator[3] ||
                ch==terminator[4]||ch==terminator[5] ||ch==terminator[6]||ch==terminator[7]||isDigit(ch);
    }

    public static boolean inNonTerminator(char ch){
        return ch==nonTerminator[0]||ch==nonTerminator[1]||ch==nonTerminator[2];
    }

    public static int valueOfLink(char a,char b){//返回左右两个符号的优先关系
        int x=-1,y=-1;
        if(isDigit(a))a='i';
        if(isDigit(b))b='i';
        for(int i=0;i<terminator.length;i++){
            if(terminator[i]==a) x=i;
            if(terminator[i]==b) y=i;
        }
        return linkTable[x][y];
    }

    public static void error(){
        errortime++;
    }

    public static int lookupReduce(String reduce){
        if(isDigit(reduce.charAt(0)))reduce="i";
        for(int z=0;z<=productionTable.length-1;z++){
            if(productionTable[z].equals(reduce))
                return z;
        }
        return -1;
    }

}
